package com.rj.framework.validation.validator;

import com.rj.framework.validation.annotation.CrossFieldValidation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 跨属性校验处理器
 */
public class CrossFieldValidator
        implements ConstraintValidator<CrossFieldValidation, Object> {

    private static final ExpressionParser PARSER = new SpelExpressionParser();

    private Expression conditionExpression;
    private Expression validationExpression;
    private Expression messageExpression;
    private String[] fields;
    private String[] dependsOn;

    @Override
    public void initialize(CrossFieldValidation constraint) {
        // 初始化校验条件表达式
        String condition = constraint.condition();
        if (condition != null && !condition.isEmpty()) {
            conditionExpression = PARSER.parseExpression(condition);
        }
        // 初始化校验表达式
        validationExpression = PARSER.parseExpression(constraint.expression());
        // 初始化错误信息表达式
        String message = constraint.message();
        if (message != null && !message.isEmpty()) {
            messageExpression = PARSER.parseExpression(message);
        }
        // 获取相关字段
        fields = constraint.fields();
        dependsOn = constraint.dependsOn();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 创建表达式上下文
        StandardEvaluationContext evalContext = new StandardEvaluationContext(value);

        // 如果需要依赖其他字段，预先获取字段值
        if (dependsOn.length > 0) {
            Map<String, Object> dependedValues = extractFieldValues(value, dependsOn);
            dependedValues.forEach(evalContext::setVariable);
        }

        // 检查条件是否满足
        if (conditionExpression != null) {
            Boolean conditionMet = conditionExpression.getValue(evalContext, Boolean.class);
            if (conditionMet == null || !conditionMet) {
                // 条件不满足，跳过校验
                return true;
            }
        }

        // 执行校验
        Boolean isValid = validationExpression.getValue(evalContext, Boolean.class);
        if (isValid == null || isValid) {
            // 校验通过
            return true;
        }

        // 校验失败，构建自定义错误信息
        context.disableDefaultConstraintViolation();

        // 创建错误消息
        String errorMessage = messageExpression != null ?
                messageExpression.getValue(evalContext, String.class) :
                context.getDefaultConstraintMessageTemplate();

        // 添加字段级别的错误信息
        for (String field : fields) {
            context.buildConstraintViolationWithTemplate(errorMessage)
                    .addPropertyNode(field)
                    .addConstraintViolation();
        }

        return false;
    }

    private Map<String, Object> extractFieldValues(Object target, String[] fieldNames) {
        // 实现字段值提取逻辑（可以使用反射或工具类）
        //TODO: 简化实现
        return Arrays.stream(fieldNames)
                .collect(Collectors.toMap(
                        Function.identity(),
                        fieldName -> getFieldValue(target, fieldName)
                ));
    }

    private Object getFieldValue(Object target, String fieldName) {
        try {
            Field field = target.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(target);
        } catch (Exception e) {
            throw new IllegalStateException("无法获取字段值: " + fieldName, e);
        }
    }
}